package com.quanxiaoha.weblog.common.utils;

import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class AddictiveLottery {
    // 基础积分范围
    private static final int MIN_POINTS = 3;    // 最小积分（提高）
    private static final int MAX_POINTS = 12;   // 最大积分（提高）
    
    // 概率衰减系数（值越大，高积分概率衰减越快）
    private static final double DECAY_FACTOR = 0.3;
    
    // 加成机制参数
    private static final double BASE_BONUS = 0.2;     // 基础加成（提高）
    private static final double EARLY_GROWTH = 0.1;   // 前期增长率（1-3次）
    private static final double LATE_GROWTH = 0.4;    // 后期增长率（4-6次，提高）
    private static final int CYCLE_COUNT = 6;         // 周期次数

    /**
     * 计算连续完成任务的加成倍率
     * @param continuousCount 连续完成次数
     * @return 加成倍率
     */
    public static double calculateBonus(int continuousCount) {
        if (continuousCount <= 0) return 1.0;
        
        // 计算在当前周期中的位置（1-6）
        int cyclePosition = ((continuousCount - 1) % CYCLE_COUNT) + 1;
        
        // 根据位置选择不同的增长率
        double growthRate = cyclePosition <= 3 ? EARLY_GROWTH : LATE_GROWTH;
        
        // 计算基础加成值
        double baseMultiplier = 1.0;
        if (cyclePosition > 3) {
            // 如果是后期（4-6次），先计算前3次的基础值
            baseMultiplier = 1.0 + BASE_BONUS * Math.pow(1 + EARLY_GROWTH, 2);
            // 然后在此基础上继续计算
            return baseMultiplier * Math.pow(1 + LATE_GROWTH, cyclePosition - 3);
        } else {
            // 前期（1-3次）使用普通计算
            return 1.0 + BASE_BONUS * Math.pow(1 + growthRate, cyclePosition - 1);
        }
    }

    /**
     * 获取任务完成奖励积分
     * @param continuousCount 连续完成任务次数
     * @return 获得的积分
     */
    public static int getRewardPoints(int continuousCount) {
        // 计算基础积分（使用概率衰减）
        double random = new SecureRandom().nextDouble();
        int basePoints = calculateWeightedRandomPoint(random);
        
        // 计算连续完成任务的加成
        double bonus = calculateBonus(continuousCount);
        
        // 计算最终积分（四舍五入）
        return (int) Math.round(basePoints * bonus);
    }

    /**
     * 根据概率衰减计算随机积分
     * @param random 0-1之间的随机数
     * @return 基础积分
     */
    public static int calculateWeightedRandomPoint(double random) {
        // 计算每个积分的权重
        double[] weights = new double[MAX_POINTS - MIN_POINTS + 1];
        double totalWeight = 0;
        
        for (int i = 0; i < weights.length; i++) {
            // 使用指数衰减计算权重
            weights[i] = Math.exp(-DECAY_FACTOR * i);
            totalWeight += weights[i];
        }
        
        // 根据权重选择积分
        double cumulative = 0;
        for (int i = 0; i < weights.length; i++) {
            cumulative += weights[i] / totalWeight;
            if (random <= cumulative) {
                return MIN_POINTS + i;
            }
        }
        
        return MIN_POINTS; // 默认返回最小积分
    }

    /**
     * 计算每个积分出现的概率
     * @param continuousCount 连续完成任务次数
     * @return 积分概率分布
     */
    public static Map<Integer, Double> calculatePointProbabilities(int continuousCount) {
        Map<Integer, Double> probabilities = new HashMap<>();
        double bonus = calculateBonus(continuousCount);
        
        // 计算每个基础积分的权重
        double[] weights = new double[MAX_POINTS - MIN_POINTS + 1];
        double totalWeight = 0;
        
        for (int i = 0; i < weights.length; i++) {
            weights[i] = Math.exp(-DECAY_FACTOR * i);
            totalWeight += weights[i];
        }
        
        // 计算每个基础积分可能产生的最终积分
        for (int i = 0; i < weights.length; i++) {
            int basePoints = MIN_POINTS + i;
            int finalPoints = (int) Math.round(basePoints * bonus);
            double prob = weights[i] / totalWeight;
            probabilities.merge(finalPoints, prob, Double::sum);
        }
        
        return probabilities;
    }


    public static Integer getPoint(int continuousCount) {

        // 计算基础积分
        double random = new SecureRandom().nextDouble();
        int basePoints = calculateWeightedRandomPoint(random);
        // 计算加成
        double bonus = calculateBonus(continuousCount);
        // 计算最终积分
        int finalPoints = (int) Math.round(basePoints * bonus);

        return finalPoints;
    }


    // 测试代码
    public static void main(String[] args) {
        // 模拟实际抽奖过程（一个完整周期）
        System.out.println("\n实际抽奖模拟：");
        int continuousCount = 0;
        int totalPoints = 0;  // 累计积分

        for (int i = 1; i <= CYCLE_COUNT*10; i++) {
            // 计算基础积分
            double random = new SecureRandom().nextDouble();
            int basePoints = calculateWeightedRandomPoint(random);
            // 计算加成
            double bonus = calculateBonus(continuousCount);
            // 计算最终积分
            int finalPoints = (int) Math.round(basePoints * bonus);
            // 更新累计积分
            totalPoints += finalPoints;

            System.out.printf("第%d次任务完成: 基础积分%d + 加成%.1f%% = %d积分 (累计: %d积分)",
                i, basePoints, (bonus - 1) * 100, finalPoints, totalPoints);
            if (i == CYCLE_COUNT) {
                System.out.print(" 【周期结束】");
            }
            System.out.println();

            continuousCount++;
        }
    }
}
